/*
 * Copyright (c) 2011 Samuel Ventura All Rights Reserved
 */
package dev2net;

import dev2net.Util.Msg;
import gnu.io.CommPortIdentifier;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ResourceBundle;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.text.BadLocationException;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.StyledDocument;

/*
 * RxTx installation on ubuntu development box
 *  - Download rxtx-2.1.7-bin-r2 an unzip it
 *  - cp RXTXcomm.jar /usr/lib/jvm/java-6-sun-1.6.0.24/jre/lib/ext
 *  - cp Linux/i686-unknown-linux-gnu/librxtxSerial.so /usr/lib/jvm/java-6-sun-1.6.0.24/jre/lib/i386
 * Windows XP installation
 *  - rxtxSerial.dll to C:\Program Files\Java\jre6\bin
 *  - RXTXcomm.jar to C:\Program Files\Java\jre6\lib\ext
 * JNLP distribution does not need this installation.
 * 
 * [-] /dev/ttyUSB0 is not detected if plugged after program startup
 *      Not reproducible anymore
 * [x] Com socket disconnection is not detected for netcat Ctrl+C
 *      New connections close and replace previous connection
 * [x] Generate launch4j exe wrapper
 *      Requires opto22.snappac.comm.jar,RXTXcomm.jar,arch-rxtx.LIB on same folder
 *      rxtx can be optionally installed to jre folder
 * [x] Script to upload
 *      Ready in misc folder
 * [x] Include native libs in JNLP
 *      Manually generated native-linux32.jar and native-win32.jar
 *      and manually added nativelib tag to master-application.jnlp
 *      manually copied them to dist/lib
 * [x] Sign JNLP distribution - Required for native libs
 *      Created on ~/NetbeansProjects/keystore
 * [x] Test JNLP distribution
 *      http://samuelventura.com/go/dev2net/
 * [x] JNLP opens no console. Application goes to background
 *      Custom swing console implemented
 * [x] Build helpers
 *      - Autogenerated date and consecutive
 *      - zip jexe generator and distexe folder
 *      - copy native libs for jnlp to dist
 */
public class Main {

    private static final SharedState sharedState = new SharedState();
    private static ServerSocket controlSocket;
    private static MmThread mmThread = new MmThread(sharedState);
    private static ConsoleThread consoleThread;
    private static JTextPane textPane;
    private static ResourceBundle rb;

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws IOException {

        rb = ResourceBundle.getBundle("dev2net/version");
        Util.out("BUILD " + rb.getString("BUILD"));
        Util.out("DATE " + rb.getString("DATE"));
        
        showUI();

        //force initialization on startup
        CommPortIdentifier.getPortIdentifiers();

        mmThread.start();
        try {
            controlSocket = new ServerSocket(2011);
            Util.out("listening on 2011");
            while (true) {
                Socket client = controlSocket.accept();
                ControlThread controlThread = new ControlThread(sharedState, client);
                controlThread.start();
            }
        } catch (IOException ex) {
            System.err.println("ioe:" + ex.getMessage());
            Util.out(ex.getMessage());
        }
    }

    public static void showUI() throws IOException {

        textPane = new JTextPane();
        textPane.setEditable(false);
        textPane.setBackground(Color.black);
        textPane.setForeground(Color.yellow);
        textPane.setFont(new Font("System", Font.PLAIN, 12));

        StyledDocument doc = textPane.getStyledDocument();
        Style def = StyleContext.getDefaultStyleContext().
                getStyle(StyleContext.DEFAULT_STYLE);
        Style out = doc.addStyle("out", def);
        StyleConstants.setForeground(out, Color.LIGHT_GRAY);
        Style err = doc.addStyle("err", def);
        StyleConstants.setForeground(err, Color.ORANGE);

        JFrame frame = new JFrame("dev2net console - build " + rb.getString("DATE"));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new JScrollPane(textPane), BorderLayout.CENTER);
        frame.setSize(600, 200);
        frame.setVisible(true);

        consoleThread = new ConsoleThread();
        consoleThread.start();

        Util.init();
    }

    private static class ConsoleThread extends Thread {

        ConsoleThread() {
            this.setName("conthread");
            this.setDaemon(true);
        }

        @Override
        public void run() {
            while (true) {
                Msg msg = Util.peek();
                if (msg != null) {
                    SwingUtilities.invokeLater(new ConsoleUpdater(msg));
                }
            }
        }
    }

    private static class ConsoleUpdater implements Runnable {

        private final int MAXLEN = 100000;
        private Msg msg;

        public ConsoleUpdater(Msg msg) {
            this.msg = msg;
        }

        @Override
        public void run() {
            try {
                StyledDocument doc = textPane.getStyledDocument();
                doc.insertString(doc.getLength(), msg.str + "\n", doc.getStyle(msg.typ));
                if (doc.getLength() > MAXLEN) {
                    doc.remove(0, doc.getLength() - MAXLEN);
                }
                textPane.setCaretPosition(doc.getLength());
            } catch (BadLocationException ex) {
                ex.printStackTrace();
            }
        }
    }
}
